#include "page.h"
#include <cstring>
#include <string>
#include <sstream>
#include <fstream>
#include "Convertor.h"
#include "file_manager.h"
#include "encode.h"
#include <io.h>
#include <assert.h>
#include <direct.h>
using namespace std;

#define CUR_PAGE (~(unsigned char)0)
#define OTHER_PAGE (~(unsigned char)0<<1)




Page::Page(string fileid1, string pageid1, PageType type1)
{
    memset(buffer, 0, sizeof(buffer));
    pageType = type1;

    pctfree = 0;
    pctused = 0;
    datanumber = 0;
    metaEnd = 0;
    dataBegin = PAGE_SIZE; //�Ӻ���ǰд
    strcpy(databaseObjectID, Conv64::to_64((int)type1, 6).c_str());
    strcpy(fileid, fileid1.c_str());
    strcpy(pageid, pageid1.c_str());
}

Page::~Page()
{
}

void Page::setPageType(PageType pageType)
{
    pageType = pageType;
}

PageType Page::getPageType()
{
    return pageType;
}

const char* Page::getFileid()
{
    return fileid;
}

const char* Page::getPageid()
{
    return pageid;
}

string Page::getFileName()
{
    stringstream ss;
    ss << "./data/data_" << fileid << ".db";
    return ss.str();
}

void Page::setNextPageid(string id)
{
    nextpageid = atoi(Conv64::to_10(id).c_str());//ת������
}

string Page::getNextPageid()
{
    //���һ��
    if (nextpageid == 0)
        return "";
    return Conv64::to_64(nextpageid, 6);
}

bool Page::isAbleToInput(Stat* content)
{
    if (isFull())
        return false;
    return dataBegin - metaEnd > getEncodeLength(content);
}

bool Page::isAbleToUpdate(Stat* content)
{
    return dataBegin - metaEnd - 20 > getEncodeLength(content);
}


//��ɾ�Ĳ�
string Page::put(Stat* content, int beginPos)
{
    string offset;
    if (beginPos == -1)
        offset = createID();
    putStrategy* str = nullptr;
    if (content->type == kStatLiteralInt)
        str = new putIntStrategy;
    else if (content->type == kStatLiteralFloat)
        str = new putFloatStrategy;
    else if (content->type == kStatLiteralString)
        str = new putStringStrategy;
    else if (content->type == kStatArray)
        str = new putArrayStrategy;
    else if (content->type == kStatLiteralNull)
        str = new putNullStrategy;
    //9.15.7
    else if (content->type == kStatLiteralBool) {
        printf("[PUT] BOOL value=%lld\n", content->ival);
        str = new putBoolStrategy;
    }
    assert(str);

    //����
    if (beginPos == -1) {
        dataBegin = dataBegin - getEncodeLength(content);
        str->put(this, content, dataBegin);
        datanumber++;
        dataType.push_back(content->type);
        dataoffset.push_back(dataBegin);
    }

    else {
        if (beginPos < dataBegin) {
            dataBegin = beginPos;
            datanumber++;
            dataType.push_back(content->type);
            dataoffset.push_back(dataBegin);
        }
        str->put(this, content, beginPos);
    }
    delete str;
    updateBuffer();
    return offset;
}

void Page::remove(const char* id)
{
    string s(id);
    string doi = s.substr(0, 6);
    string fid = s.substr(6, 3);
    string bid = s.substr(9, 6);
    string offset = s.substr(15, 3);
    if (strcmp(doi.c_str(), databaseObjectID) != 0 || strcmp(fid.c_str(), fileid) != 0 || strcmp(bid.c_str(), pageid) != 0)
        throw "���ݲ�ƥ��";
    remove(atoi(Conv64::to_10(offset).c_str()));//��offset��Ϊ����ɾȥ
}



void Page::update(const char* id, Stat* newContent)
{
    string s(id);
    string doi = s.substr(0, 6);
    string fid = s.substr(6, 3);
    string bid = s.substr(9, 6);
    string rid = s.substr(15, 3);
    if (strcmp(doi.c_str(), databaseObjectID) != 0 || strcmp(fid.c_str(), fileid) != 0 || strcmp(bid.c_str(), pageid) != 0)
        throw "���ݲ�ƥ��";
    int r = atoi(Conv64::to_10(rid).c_str());

    //ԭλ�ÿ��Ը���
    bool updateAtCurPos = false;
    int newlen = getEncodeLength(newContent);
    if (r == 0)
        updateAtCurPos = PAGE_SIZE - dataoffset[r] >= newlen;
    else
        updateAtCurPos = dataoffset[r - 1] - dataoffset[r] >= newlen;
    if (updateAtCurPos) {
        put(newContent, dataoffset[r]);
        return;
    }

    //ԭλ�ò��ɸ��£�������ҳ�ڿ���
    bool updateAtCurBlock = isAbleToUpdate(newContent);
    if (updateAtCurBlock) {
        dataType[r] = kStatUpdated;
        int curpos = dataoffset[r];
        buffer[curpos++] = CUR_PAGE;
        string offsetstr = Conv64::to_64(datanumber - r);
        int offset = offsetstr.size() + 1;
        if (r == 0) {
            if (!PAGE_SIZE - dataoffset[r] >= offset)
                throw "������̫���޷�д��";
        }
        else {
            if (dataoffset[r - 1] - dataoffset[r] >= newlen)
                throw "������̫���޷�д��";
        }
        strcpy(curpos + buffer, offsetstr.c_str());
        put(newContent);
    }
    else {
        //��ҳ���ܸ���
        Page* page = FileManager::getInstance()->getLastAvailablePage(fileid);
        if (page == nullptr) {
            // 修复：处理getLastAvailablePage返回空指针的情况
            throw "Failed to get available page for update";
        }
        dataType[r] = kStatUpdated;
        page->put(newContent);
        int curpos = dataoffset[r];
        buffer[curpos++] = OTHER_PAGE;
        int blkOffset = atoi(Conv64::to_10(string(page->getPageid())).c_str()) - atoi(Conv64::to_10(string(getPageid())).c_str());
        int rowid = page->datanumber + 1;
        string blkOffsetStr = Conv64::to_64(blkOffset);
        string rowidStr = Conv64::to_64(rowid);
        int offset = blkOffsetStr.size() + rowidStr.size() + 2;
        if (r == 0) {
            if (!PAGE_SIZE - dataoffset[r] >= offset)
                throw "������̫���޷�д��";
        }
        else {
            if (dataoffset[r - 1] - dataoffset[r] >= newlen)
                throw "������̫���޷�д��";
        }
        strcpy(buffer + curpos, blkOffsetStr.c_str());
        curpos++;
        strcpy(buffer + curpos, rowidStr.c_str());
        curpos++;
    }
}

Stat* Page::get(const char* id)
{
    string s(id);
    string doi = s.substr(0, 6);
    string fid = s.substr(6, 3);
    string bid = s.substr(9, 6);
    string offset = s.substr(15, 3);
    if (strcmp(doi.c_str(), databaseObjectID) != 0 || strcmp(fid.c_str(), fileid) != 0 || strcmp(bid.c_str(), pageid) != 0)
        throw "���ݲ�ƥ��";
    return get(atoi(Conv64::to_10(offset).c_str()));
}

vector<Stat*> Page::get(const char* fromid, const char* toid)
{
    string fs(fromid);
    string fdoi = fs.substr(0, 6);
    string ffid = fs.substr(6, 3);
    string fbid = fs.substr(9, 6);
    string frid = fs.substr(15, 3);
    string ts(toid);
    string tdoi = ts.substr(0, 6);
    string tfid = ts.substr(6, 3);
    string tbid = ts.substr(9, 6);
    string trid = ts.substr(15, 3);
    if (strcmp(fdoi.c_str(), databaseObjectID) != 0 || strcmp(ffid.c_str(), fileid) != 0 || strcmp(fbid.c_str(), pageid) != 0 || strcmp(tdoi.c_str(), databaseObjectID) != 0 || strcmp(tfid.c_str(), fileid) != 0 || strcmp(tbid.c_str(), pageid) != 0)
        throw "���ݲ�ƥ��";
    return get(atoi(Conv64::to_10(frid).c_str()), atoi(Conv64::to_10(trid).c_str()));
}

vector<Stat*> Page::getFromIDToEnd(const char* fromid)
{
    string s(fromid);
    string doi = s.substr(0, 6);
    string fid = s.substr(6, 3);
    string bid = s.substr(9, 6);
    string rid = s.substr(15, 3);
    if (strcmp(doi.c_str(), databaseObjectID) != 0 || strcmp(fid.c_str(), fileid) != 0 || strcmp(bid.c_str(), pageid) != 0)
        throw "���ݲ�ƥ��";
    return get(atoi(Conv64::to_10(rid).c_str()), datanumber - 1);
}

vector<Stat*> Page::getFromFrontToID(const char* toid)
{
    string s(toid);
    string doi = s.substr(0, 6);
    string fid = s.substr(6, 3);
    string bid = s.substr(9, 6);
    string rid = s.substr(15, 3);
    if (strcmp(doi.c_str(), databaseObjectID) != 0 || strcmp(fid.c_str(), fileid) != 0 || strcmp(bid.c_str(), pageid) != 0)
        throw "���ݲ�ƥ��";
    return get(0, atoi(Conv64::to_10(rid).c_str()));
}

vector<Stat*> Page::getFromFrontToEnd()
{
    return get(0, datanumber - 1);
}

string Page::createID()
{
    stringstream ss;
    ss << databaseObjectID << fileid << pageid << Conv64::to_64(datanumber, 3);	//id���:ObjectID + �ļ�id + ҳid + ��λ64���Ƽ�¼id 
    return ss.str();
}

bool Page::writePage()
{
    //�����ļ�
    int cdecl_temp = _mkdir("data");
    int isExist = _access(getFileName().c_str(), 0);
    if (isExist == -1) {
        ofstream o(getFileName(), ios::out);
        o.close();
    }
    //��
    fstream nodeFile(getFileName(), ios::binary | ios::out | ios::in);
    if (!nodeFile)
        return false;
    updateBuffer();
    nodeFile.seekp(PAGE_SIZE * atoi(Conv64::to_10(pageid).c_str()));
    nodeFile.write(buffer, PAGE_SIZE);
    nodeFile.close();
    return true;
}

bool Page::readPage()
{
    fstream nodeFile(getFileName(), ios::binary | ios::in);
    if (!nodeFile)
        return false;
    nodeFile.seekg(PAGE_SIZE * atoi(Conv64::to_10(pageid).c_str()));
    nodeFile.read(buffer, PAGE_SIZE);
    nodeFile.close();
    return true;
}

void Page::writeToBuffer(int begin, char* text)
{
    strcpy(buffer + begin, text);
}

int Page::getMetaEnd()
{
    return metaEnd;
}

void Page::setMetaEnd(int metaEnd1)
{
    metaEnd = metaEnd1;
}

int Page::getDataBegin()
{
    return dataBegin;
}

void Page::setDataBegin(int dataBegin1)
{
    dataBegin = dataBegin1;
}


void Page::updateBuffer()
{
    char buff[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    metaEnd = 0;
    memcpy(buffer + metaEnd, databaseObjectID, sizeof(databaseObjectID));
    metaEnd += sizeof(databaseObjectID) - 1;
    memcpy(buffer + metaEnd, fileid, sizeof(fileid));
    metaEnd += sizeof(fileid) - 1;
    memcpy(buffer + metaEnd, pageid, sizeof(pageid));
    metaEnd += sizeof(pageid);

    strcpy(buff, Conv64::to_64(datanumber).c_str());
    strcpy(buffer + metaEnd, buff);
    metaEnd += strlen(buff) + 1;

    strcpy(buff, Conv64::to_64(nextpageid).c_str());
    strcpy(buffer + metaEnd, buff);
    metaEnd += strlen(buff) + 1;

    for (int i = 0; i < datanumber; i++) {
        strcpy(buff, Conv64::to_64(dataoffset[i]).c_str());
        strcpy(buffer + metaEnd, buff);
        metaEnd += strlen(buff) + 1;
    }
    for (int i = 0; i < datanumber; i++) {
        strcpy(buff, Conv64::to_64(dataType[i]).c_str());
        strcpy(buffer + metaEnd, buff);
        metaEnd += strlen(buff) + 1;
    }

    strcpy(buff, Conv64::to_64(dataBegin).c_str());
    strcpy(buffer + metaEnd, buff);
    metaEnd += strlen(buff) + 1;

    pctfree = (dataBegin - metaEnd - 2 * sizeof(float) + 0.0f) / PAGE_SIZE;
    pctused = (metaEnd + (PAGE_SIZE - dataBegin) + 2 * sizeof(float)) / PAGE_SIZE;
    memcpy(buffer + metaEnd, &pctfree, sizeof(pctfree));
    metaEnd += sizeof(pctfree);
    memcpy(buffer + metaEnd, &pctused, sizeof(fileid));
    metaEnd += sizeof(pctused);
}

void Page::updateMetaData()
{
    size_t location = 0;
    char buff[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    strcpy(buff, buffer + location);
    location += strlen(buff) + 1;
    string s(buff);
    strcpy(databaseObjectID, s.substr(0, 6).c_str());
    strcpy(fileid, s.substr(6, 3).c_str());
    strcpy(pageid, s.substr(9, 6).c_str());

    strcpy(buff, buffer + location);
    location += strlen(buff) + 1;
    datanumber = atoi(Conv64::to_10(buff).c_str());

    strcpy(buff, buffer + location);
    location += strlen(buff) + 1;
    nextpageid = atoi(Conv64::to_10(buff).c_str());

    for (int i = 0; i < datanumber; i++) {
        strcpy(buff, buffer + location);
        location += strlen(buff) + 1;
        dataoffset.push_back(atoi(Conv64::to_10(buff).c_str()));
    }
    for (int i = 0; i < datanumber; i++) {
        strcpy(buff, buffer + location);
        location += strlen(buff) + 1;
        dataType.push_back((StatType)atoi(Conv64::to_10(buff).c_str()));
    }

    strcpy(buff, buffer + location);
    location += strlen(buff) + 1;
    dataBegin = atoi(Conv64::to_10(buff).c_str());

    memcpy(&pctfree, buffer + location, sizeof(pctfree));
    location += sizeof(pctfree);
    memcpy(&pctused, buffer + location, sizeof(fileid));
    location += sizeof(pctused);
}

bool Page::isFull()
{
    if (pctfree < PCT_FREE_THRESHOLD || pctused>PCT_USED_THRESHOLD)
        return true;
    return false;
}



Stat* Page::get(int idx)
{
    StatType type = dataType[idx];
    getStrategy* str = getGetStrategy(type);
    Stat* res = str->get(this, idx);
    delete str;
    return res;
}


void Page::remove(int idx)
{
    if (dataType[idx] == kStatUpdated) {
        char buff[PAGE_SIZE];
        memset(buff, 0, sizeof(buff));
        int from = dataoffset[idx];
        if (buffer[from] == CUR_PAGE) {
            strcpy(buff, buffer + from + 1);
            int newrid = atoi(Conv64::to_10(getPageid()).c_str()) + atoi(Conv64::to_10(buff).c_str());
            remove(newrid);
        }
        else if (buffer[from] == OTHER_PAGE) {
            from++;
            strcpy(buff, buffer + from);
            from += strlen(buff) + 1;
            int blkid = atoi(Conv64::to_10(getPageid()).c_str()) + atoi(Conv64::to_10(buff).c_str());
            strcpy(buff, buffer + from);
            from += strlen(buff) + 1;
            int newrid = atoi(Conv64::to_10(buff).c_str());
            Page* newblk = FileManager::getInstance()->getPage(getFileid(), Conv64::to_64(blkid, 6));
            newblk->remove(newrid);
        }
    }

    //�����Ѿ�ɾ����ҳ
    bool isRecycleable = true;
    dataType[idx] = kStatDeleted;
    for (auto type : dataType) {
        if (type != kStatDeleted) {
            isRecycleable = false;
            break;
        }
    }
    if (isRecycleable) {
        dataoffset.clear();
        dataType.clear();
        datanumber = 0;
        dataBegin = PAGE_SIZE;
        updateBuffer();
    }
}

int Page::getEncodeLength(Stat* e)
{
    if (e->type == kStatLiteralFloat)
        return sizeof(double);
    else if (e->type == kStatLiteralInt)
        return Conv64::to_64(e->ival).length() + 1;
    //9.15.7
    else if (e->type == kStatLiteralBool) {
        printf("[ENC_LEN] BOOL=1\n");
        return sizeof(char);
    }
    else if (e->type == kStatLiteralString)
    {
        char buff[PAGE_SIZE];
        memset(buff, 0, sizeof(buff));
        b64_encode(e->name, strlen(e->name), buff);
        return strlen(buff) + 1;
    }
    else if (e->type == kStatLiteralNull)
        return 0;
    else if (e->type == kStatArray)
        return statToString(e).length() + 1;
}

//��Statת��Ϊstring
string Page::statToString(Stat* e)
{
    char arrbuffer[PAGE_SIZE];
    memset(arrbuffer, 0, sizeof(arrbuffer));

    int pos = 0;		

    //#����
    for (auto stat : *e->statList) {
        arrbuffer[pos++] = stat->type;
    }
    arrbuffer[pos++] = '#';

    for (auto stat : *e->statList) {

        //int
        if (stat->type == kStatLiteralInt) {
            string content = Conv64::to_64(stat->ival);	//ת��Ϊ64����String
            strcpy(arrbuffer + pos, content.c_str());
            pos += content.size();
            pos++;
        }

        //double
        else if (stat->type == kStatLiteralFloat) {
            memcpy(arrbuffer + pos, &stat->fval, sizeof(double));
            pos += sizeof(double);
        }

        //string
        else if (stat->type == kStatLiteralString) {
            char buff[PAGE_SIZE];
            memset(buff, 0, sizeof(buff));
            b64_encode(stat->name, strlen(stat->name), buff);
            strcpy(arrbuffer + pos, buff);
            pos += strlen(buff);
            pos++;
        }

        //Array
        else if (stat->type == kStatArray) {
            string encode = statToString(stat);
            strcpy(arrbuffer + pos, encode.data());
            pos += encode.size();
            pos++;
        }

        //9.15.7
        else if (stat->type == kStatLiteralBool) {
            //arrbuffer[pos++] = stat->type;
            arrbuffer[pos++] = stat->ival ? 1 : 0; // 保存布尔值
        }
    }
    char dst[PAGE_SIZE];
    memset(dst, 0, sizeof(dst));
    b64_encode(arrbuffer, pos, dst);
    return string(dst);
}

//����
Stat* Page::stringToStat(string str)
{
    vector<Stat*>* res = new vector<Stat*>();
    if (str == "")
        return Stat::makeArray(res);
    char buff[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    b64_decode(str.data(), str.length(), buff);

    int pos = 0;
    vector<StatType> types;
    while (buff[pos] != '#') {
        types.push_back((StatType)buff[pos]);
        pos++;
    }
    pos++;
    for (int i = 0; i < types.size(); i++) {
        if (types[i] == kStatArray) {
            char arrbuff[PAGE_SIZE];
            memset(arrbuff, 0, sizeof(arrbuff));
            strcpy(arrbuff, buff + pos);
            res->push_back(stringToStat(arrbuff));
            pos += strlen(arrbuff) + 1;
        }
        else if (types[i] == kStatLiteralInt) {
            int len = strlen(buff + pos);
            char arrbuff[PAGE_SIZE];
            char decode[PAGE_SIZE];
            memset(arrbuff, 0, sizeof(arrbuff));
            memset(decode, 0, sizeof(decode));
            strcpy(arrbuff, buff + pos);
            strcpy(decode, Conv64::to_10(arrbuff).c_str());
            Stat* e = Stat::makeLiteral((int64_t)atoi(decode));
            res->push_back(e);
            pos += len + 1;
        }
        else if (types[i] == kStatLiteralFloat) {
            int len = sizeof(double);
            double d;
            memcpy(&d, buff + pos, sizeof(d));
            Stat* e = Stat::makeLiteral(d);
            res->push_back(e);
            pos += len;
        }
        else if (types[i] == kStatLiteralString) {
            char arrbuff[PAGE_SIZE];
            char decode[PAGE_SIZE];
            memset(arrbuff, 0, sizeof(arrbuff));
            memset(decode, 0, sizeof(decode));
            strcpy(arrbuff, buff + pos);
            b64_decode(arrbuff, strlen(arrbuff), decode);
            Stat* e = Stat::makeLiteral(decode);
            res->push_back(e);
            pos += strlen(arrbuff) + 1;
        }
        //9.15.7
        else if (types[i] == kStatLiteralBool) {
            char val = buff[pos++];
            res->push_back(Stat::makeLiteral(val != 0));
        }
    }
    return Stat::makeArray(res);
}

vector<Stat*> Page::get(int fromidx, int toidx)
{
    vector<Stat*> res;
    getStrategy* str[8];
    str[0] = getGetStrategy(kStatLiteralInt);
    str[1] = getGetStrategy(kStatLiteralFloat);
    str[2] = getGetStrategy(kStatLiteralString);
    str[3] = getGetStrategy(kStatArray);
    str[4] = getGetStrategy(kStatDeleted);
    str[5] = getGetStrategy(kStatUpdated);
    str[6] = getGetStrategy(kStatLiteralNull);
    //9.15.7
    str[7] = getGetStrategy(kStatLiteralBool);

    for (int i = fromidx; i <= toidx; i++) {
        StatType type = dataType[i];
        if (type == kStatLiteralInt)
            res.push_back(str[0]->get(this, i));
        else if (type == kStatLiteralFloat)
            res.push_back(str[1]->get(this, i));
        else if (type == kStatLiteralString)
            res.push_back(str[2]->get(this, i));
        else if (type == kStatArray)
            res.push_back(str[3]->get(this, i));
        else if (type == kStatDeleted)
            res.push_back(str[4]->get(this, i));
        else if (type == kStatUpdated)
            res.push_back(str[5]->get(this, i));
        else if (type == kStatLiteralNull)
            res.push_back(str[6]->get(this, i));
        //9.15.7
        else if (type == kStatLiteralBool)
            res.push_back(str[7]->get(this, i));

    }
    for (int i = 0; i < 8; i++) delete str[i];

    return res;
}

bool Page::putIntStrategy::put(Page* page, Stat* e, int from)
{
    string content = Conv64::to_64(e->ival);
    page->dataBegin = from;
    strcpy(page->buffer + page->dataBegin, content.c_str());
    page->datanumber++;
    page->dataType.push_back(e->type);
    page->dataoffset.push_back(page->dataBegin);
    page->updateBuffer();
    return true;
}

//9.15.7
bool Page::putBoolStrategy::put(Page* page, Stat* e, int from) {
    // 将 BOOL 类型的值转换为字节
    char value = e->ival ? 1 : 0;

    // 将值写入页面的指定位置
    page->buffer[from] = value;

    // 更新页面的元数据
    page->datanumber++;
    page->dataType.push_back(e->type);
    page->dataoffset.push_back(from);

    // 更新缓冲区
    page->updateBuffer();

    return true;
}

bool Page::putFloatStrategy::put(Page* page, Stat* e, int from)
{
    page->dataBegin = from;
    memcpy(page->buffer + page->dataBegin, &e->fval, sizeof(double));
    page->datanumber++;
    page->dataType.push_back(e->type);
    page->dataoffset.push_back(page->dataBegin);
    page->updateBuffer();
    return true;
}

bool Page::putStringStrategy::put(Page* page, Stat* e, int from)
{
    char buff[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    b64_encode(e->name, strlen(e->name), buff);
    page->dataBegin = from;
    strcpy(page->buffer + page->dataBegin, buff);
    page->datanumber++;
    page->dataType.push_back(e->type);
    page->dataoffset.push_back(page->dataBegin);
    page->updateBuffer();
    return true;
}

bool Page::putArrayStrategy::put(Page* page, Stat* e, int from)
{
    string res = statToString(e);
    strcpy(page->buffer + from, res.data());

    return true;
}

bool Page::putNullStrategy::put(Page* page, Stat* e, int from)
{
    //9.16 null值插入
    page->buffer[from] = 0;


    page->datanumber++;
    page->dataType.push_back(e->type);
    page->dataoffset.push_back(page->dataBegin);
    page->updateBuffer();
    return true;
}


Stat* Page::getStringStrategy::get(Page* page, int idx)
{
    char buff[PAGE_SIZE];
    char decode[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    memset(decode, 0, sizeof(decode));
    int from = page->dataoffset[idx];
    strcpy(buff, page->buffer + from);

    //9.16 null值
    // 如果页面里存的是空串，说明原本是 NULL
    if (buff[0] == '\0' && page->dataType[idx] == kStatLiteralNull)
        return Stat::makeNullLiteral();

    b64_decode(buff, strlen(buff), decode);
    Stat* e = Stat::makeLiteral(decode);
    return e;
}

Stat* Page::getFloatStrategy::get(Page* page, int idx)
{
    double res;
    int from = page->dataoffset[idx];
    memcpy(&res, page->buffer + from, sizeof(res));
    Stat* e = Stat::makeLiteral(res);
    return e;
}

Stat* Page::getIntStrategy::get(Page* page, int idx)
{
    char buff[PAGE_SIZE];
    char decode[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    memset(decode, 0, sizeof(decode));
    int from = page->dataoffset[idx];
    strcpy(buff, page->buffer + from);
    strcpy(decode, Conv64::to_10(buff).c_str());
    Stat* e = Stat::makeLiteral((int64_t)atoi(decode));
    return e;
}

//9.15.7
Stat* Page::getBoolStrategy::get(Page* page, int idx)
{
    // 从页面中读取布尔值
    char value;
    int from = page->dataoffset[idx];
    value = page->buffer[from];

    // 将布尔值封装成 Stat 对象
    Stat* e = Stat::makeLiteral(value != 0);
    return e;
}

Stat* Page::getArrayStrategy::get(Page* page, int idx)
{
    char buff[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    int from = page->dataoffset[idx];
    strcpy(buff, page->buffer + from);
    return stringToStat(buff);
}

Stat* Page::getDeletedStrategy::get(Page* page, int idx)
{
    return nullptr;
}

Stat* Page::getUpdatedStrategy::get(Page* page, int idx)
{
    char buff[PAGE_SIZE];
    memset(buff, 0, sizeof(buff));
    int from = page->dataoffset[idx];
    if (page->buffer[from] == CUR_PAGE) {
        strcpy(buff, page->buffer + from + 1);
        int newrid = atoi(Conv64::to_10(page->getPageid()).c_str()) + atoi(Conv64::to_10(buff).c_str());
        return page->get(newrid);
    }
    else if (page->buffer[from] == OTHER_PAGE) {
        from++;
        strcpy(buff, page->buffer + from);
        from += strlen(buff) + 1;
        int blkid = atoi(Conv64::to_10(page->getPageid()).c_str()) + atoi(Conv64::to_10(buff).c_str());
        strcpy(buff, page->buffer + from);
        from += strlen(buff) + 1;
        int newrid = atoi(Conv64::to_10(buff).c_str());
        Page* newpage = FileManager::getInstance()->getPage(page->getFileid(), Conv64::to_64(blkid, 6));
        return newpage->get(newrid);
    }
}

Stat* Page::getNullStrategy::get(Page* blk, int idx)
{
    //9.16 null值
    return Stat::makeNullLiteral();
    //return nullptr;
}
